package com.adv.ems.manager.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.adv.ems.enums.CollectPointWarningTypeEnum;
import com.adv.ems.model.dto.TimeRangeDTO;
import com.adv.ems.service.WarningService;
import com.adv.ems.utils.EmsUtil;
import com.adv.ems.db.mapper.EnergyFeeInfoMapper;
import com.adv.ems.db.entity.EnergyFeeInfoDO;
import com.adv.ems.manager.EnergyFeeInfoManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class EnergyFeeInfoManagerImpl extends BaseManagerImpl<EnergyFeeInfoMapper, EnergyFeeInfoDO> implements EnergyFeeInfoManager {
    @Resource
    WarningService warningService;

    @Override
    public EnergyFeeInfoDO getMatchItem(Long energyId, Date hour, Double increaseRealValue, Long buildingId, Long instituteId, String areaCode) {
        List<EnergyFeeInfoDO> list = getAllMap()
                .values()
                .stream()
                .filter(f -> f.getEnergyId().equals(energyId))
                .filter(f -> isInNumberRange(f, increaseRealValue))
                .filter(f -> isInTimeRange(f, hour))
                .collect(Collectors.toList());
        if (list.isEmpty()) {
            return null;
        }
        if(buildingId != null) {
            Optional<EnergyFeeInfoDO> first = list.stream().filter(f -> buildingId.equals(f.getBuildingId())).findFirst();
            if(first.isPresent()) {
                return first.get();
            }
        }
        if (instituteId != null) {
            Optional<EnergyFeeInfoDO> first = list.stream().filter(f -> instituteId.equals(f.getInstituteId())).findFirst();
            if(first.isPresent()) {
                return first.get();
            }
        }
        if (areaCode != null && !areaCode.isEmpty()) {
            Optional<EnergyFeeInfoDO> first = list.stream().filter(f -> EmsUtil.isBelongChildCityAreaCode(f.getAreaCode(), areaCode)).findFirst();
            if(first.isPresent()) {
                return first.get();
            }
        }
        Optional<EnergyFeeInfoDO> first = list.stream().filter(f -> f.getBuildingId() == null && f.getInstituteId() == null && !StringUtils.hasLength(f.getAreaCode())).findFirst();
        return first.orElse(null);
    }

    @Override
    public void deleteById(Long id) {
        removeById(id);
    }

    private boolean isInNumberRange(EnergyFeeInfoDO fee, Double increaseRealValue) {
        if (!StringUtils.hasLength(fee.getNumRange())) {
            return true;
        }
        try {
            String[] split = fee.getNumRange().trim().split(",");
            String left = split[0];
            String right = split[1];
            boolean leftEq = left.contains("[");
            Double leftValue = left.length() > 1 ? Double.parseDouble(split[0].substring(1)) : Double.MIN_VALUE;
            boolean rightEq = right.contains("]");
            Double rightValue = right.length() > 1 ? Double.parseDouble(right.substring(0, right.length() - 1)) : Double.MAX_VALUE;
            if (increaseRealValue < leftValue) {
                return false;
            }
            if (!leftEq && increaseRealValue.equals(leftValue)) {
                return false;
            }
            if (increaseRealValue > rightValue) {
                return false;
            }
            return rightEq || !increaseRealValue.equals(rightValue);
        }catch (Exception e) {
            String msg = String.format("能源货币费用配置【ID:%s】月度累积格式【%s】错误【%s】",fee.getId(), fee.getNumRange(), e.getMessage());
            log.error(msg, e);
            warningService.pushCollectPointWarning(null, fee.getId(), EnergyFeeInfoDO.class,CollectPointWarningTypeEnum.EXCEPTION_DATA, fee.getId().toString(), msg);
            return false;
        }
    }
    private boolean isInTimeRange(EnergyFeeInfoDO fee, Date hour) {
        if (!StringUtils.hasLength(fee.getTimeRange())) {
            return true;
        }
        try {
            List<Map> range = JSONUtil.toList(fee.getTimeRange(), Map.class);
            for (Map m : range) {
                for (Object timeFormat: m.keySet()) {
                    TimeRangeDTO bean = JSONUtil.toBean(m.get(timeFormat).toString(), TimeRangeDTO.class);
                    String format = DateUtil.format(hour, timeFormat.toString());
                    int now = Integer.parseInt(format);
                    int from = Integer.parseInt(bean.getFrom());
                    int end = Integer.parseInt(bean.getEnd());
                    if (now < from || now >= end) {
                        return false;
                    }
                }
            }
        }catch (Exception e) {
            String msg = String.format("能源货币费用配置【ID:%s】月度累积格式【%s】错误【%s】",fee.getId(), fee.getNumRange(), e.getMessage());
            log.error(msg, e);
            warningService.pushCollectPointWarning(null, fee.getId(), EnergyFeeInfoDO.class, CollectPointWarningTypeEnum.EXCEPTION_DATA, fee.getId().toString(), msg);
            return false;
        }
        return true;
    }
}
